// src/main/java/cn/edu/tju/elm/controller/wallet/WalletController.java
package cn.edu.tju.elm.controller.wallet;

import cn.edu.tju.elm.model.dto.*;
import cn.edu.tju.elm.model.VirtualWallet;
import cn.edu.tju.elm.model.WalletTransaction;
import cn.edu.tju.elm.service.VirtualWalletService;
import cn.edu.tju.elm.service.CreditService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/wallet")
@Tag(name = "wallet-controller", description = "钱包操作相关接口")
public class WalletController {

    @Autowired
    private VirtualWalletService walletService;

    @Autowired
    private CreditService creditService;

    @PostMapping("/create")
    @Operation(summary = "创建用户钱包", description = "为用户创建新的虚拟钱包")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "创建成功"),
        @ApiResponse(responseCode = "400", description = "创建失败")
    })
    public ResponseEntity<WalletDTO> createWallet(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId) {
        try {
            VirtualWallet wallet = walletService.createWallet(userId);
            return ResponseEntity.ok(convertToWalletDTO(wallet));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @GetMapping("/info")
    @Operation(summary = "获取钱包信息", description = "查询用户钱包的详细信息")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "获取成功"),
        @ApiResponse(responseCode = "400", description = "获取失败")
    })
    public ResponseEntity<WalletDTO> getWalletInfo(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId) {
        try {
            VirtualWallet wallet = walletService.getWalletByUserId(userId);
            return ResponseEntity.ok(convertToWalletDTO(wallet));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @GetMapping("/balance")
    @Operation(summary = "查询总余额", description = "获取用户钱包的总余额")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "获取成功"),
        @ApiResponse(responseCode = "400", description = "获取失败")
    })
    public ResponseEntity<BigDecimal> getBalance(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId) {
        try {
            BigDecimal balance = walletService.getBalance(userId);
            return ResponseEntity.ok(balance);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(BigDecimal.ZERO);
        }
    }

    @GetMapping("/available-balance")
    @Operation(summary = "查询可用余额", description = "获取用户钱包的可用余额（扣除冻结金额后）")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "获取成功"),
        @ApiResponse(responseCode = "400", description = "获取失败")
    })
    public ResponseEntity<BigDecimal> getAvailableBalance(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId) {
        try {
            BigDecimal availableBalance = walletService.getAvailableBalance(userId);
            return ResponseEntity.ok(availableBalance);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(BigDecimal.ZERO);
        }
    }

    @PostMapping("/recharge")
    @Operation(summary = "钱包充值", description = "为钱包进行充值操作")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "充值成功"),
        @ApiResponse(responseCode = "400", description = "充值失败")
    })
    public ResponseEntity<TransactionDTO> recharge(@RequestBody RechargeRequestDTO request) {
        try {
            request.validate();
            WalletTransaction transaction = walletService.recharge(
                request.getUserId(), 
                request.getAmount()
            );
            return ResponseEntity.ok(convertToTransactionDTO(transaction));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/withdraw")
    @Operation(summary = "钱包提现", description = "从钱包进行提现操作")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "提现成功"),
        @ApiResponse(responseCode = "400", description = "提现失败")
    })
    public ResponseEntity<TransactionDTO> withdraw(@RequestBody WithdrawRequestDTO request) {
        try {
            request.validate();
            WalletTransaction transaction = walletService.withdraw(
                request.getUserId(), 
                request.getAmount()
            );
            return ResponseEntity.ok(convertToTransactionDTO(transaction));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/pay")
    @Operation(summary = "钱包支付", description = "使用钱包向指定收款方进行支付，收款方资金将暂时冻结")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "支付成功"),
        @ApiResponse(responseCode = "400", description = "支付失败")
    })
    public ResponseEntity<List<TransactionDTO>> pay(
            @Parameter(description = "付款方用户ID", required = true) @RequestParam Long fromUserId,
            @Parameter(description = "收款方用户ID", required = true) @RequestParam Long toUserId,
            @Parameter(description = "支付金额", required = true) @RequestParam BigDecimal amount,
            @Parameter(description = "支付描述") @RequestParam(required = false) String description) {
        try {
            if (fromUserId == null || toUserId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }
            if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
                throw new IllegalArgumentException("支付金额必须大于0");
            }
            if (fromUserId.equals(toUserId)) {
                throw new IllegalArgumentException("不能向自己支付");
            }
            
            List<WalletTransaction> transactions = walletService.transfer(
                fromUserId, 
                toUserId, 
                amount, 
                description
            );
            List<TransactionDTO> dtos = transactions.stream()
                    .map(this::convertToTransactionDTO)
                    .collect(Collectors.toList());
            return ResponseEntity.ok(dtos);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/transfer")
    @Operation(summary = "用户转账", description = "用户之间的钱包转账，收款方资金将暂时冻结")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "转账成功"),
        @ApiResponse(responseCode = "400", description = "转账失败")
    })
    public ResponseEntity<List<TransactionDTO>> transfer(@RequestBody TransferRequestDTO request) {
        try {
            request.validate();
            List<WalletTransaction> transactions = walletService.transfer(
                request.getFromUserId(), 
                request.getToUserId(), 
                request.getAmount(), 
                request.getDescription()
            );
            List<TransactionDTO> dtos = transactions.stream()
                    .map(this::convertToTransactionDTO)
                    .collect(Collectors.toList());
            return ResponseEntity.ok(dtos);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/credit-pay")
    @Operation(summary = "信用支付", description = "使用信用额度进行支付（仅限VIP用户）")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "支付成功"),
        @ApiResponse(responseCode = "400", description = "支付失败"),
        @ApiResponse(responseCode = "403", description = "非VIP用户")
    })
    public ResponseEntity<TransactionDTO> payWithCredit(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId,
            @Parameter(description = "支付金额", required = true) @RequestParam BigDecimal amount) {
        try {
            WalletTransaction transaction = walletService.payWithCredit(userId, amount);
            return ResponseEntity.ok(convertToTransactionDTO(transaction));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/credit-repay")
    @Operation(summary = "信用还款", description = "偿还信用欠款")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "还款成功"),
        @ApiResponse(responseCode = "400", description = "还款失败")
    })
    public ResponseEntity<TransactionDTO> repayCredit(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId,
            @Parameter(description = "还款金额", required = true) @RequestParam BigDecimal amount) {
        try {
            WalletTransaction transaction = walletService.repayCredit(userId, amount);
            return ResponseEntity.ok(convertToTransactionDTO(transaction));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/freeze")
    @Operation(summary = "冻结资金", description = "冻结钱包中的部分资金")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "冻结成功"),
        @ApiResponse(responseCode = "400", description = "冻结失败")
    })
    public ResponseEntity<TransactionDTO> freeze(
            @Parameter(description = "用户ID", required = true) @RequestParam Long userId,
            @Parameter(description = "冻结金额", required = true) @RequestParam BigDecimal amount) {
        try {
            WalletTransaction transaction = walletService.freeze(userId, amount);
            return ResponseEntity.ok(convertToTransactionDTO(transaction));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    @PostMapping("/unfreeze")
    @Operation(summary = "确认收货解冻资金", description = "客户确认收货后解冻商家账户中的冻结资金")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "解冻成功"),
        @ApiResponse(responseCode = "400", description = "解冻失败"),
        @ApiResponse(responseCode = "403", description = "无权操作")
    })
    public ResponseEntity<TransactionDTO> unfreeze(
            @Parameter(description = "用户ID（付款方）", required = true) @RequestParam Long userId,
            @Parameter(description = "交易ID（转入冻结交易ID）", required = true) @RequestParam Long transactionId) {
        try {
            if (userId == null) {
                throw new IllegalArgumentException("用户ID不能为空");
            }
            if (transactionId == null) {
                throw new IllegalArgumentException("交易ID不能为空");
            }
            
            WalletTransaction transaction = walletService.unfreeze(userId, transactionId);
            return ResponseEntity.ok(convertToTransactionDTO(transaction));
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(null);
        }
    }

    

    // DTO转换方法
    private WalletDTO convertToWalletDTO(VirtualWallet wallet) {
        WalletDTO dto = new WalletDTO();
        dto.setId(wallet.getId());
        dto.setUserId(wallet.getUserId());
        dto.setBalance(wallet.getBalance());
        dto.setFrozenAmount(wallet.getFrozenAmount());
        dto.setCreditLimit(wallet.getCreditLimit());
        dto.setUsedCredit(wallet.getUsedCredit());
        dto.setAvailableBalance(wallet.getAvailableBalance());
        dto.setIsActive(wallet.getIsActive());
        dto.setCreateTime(wallet.getCreateTime());
        return dto;
    }

    private TransactionDTO convertToTransactionDTO(WalletTransaction transaction) {
        TransactionDTO dto = new TransactionDTO();
        dto.setId(transaction.getId());
        dto.setWalletId(transaction.getWalletId());
        dto.setTransactionType(transaction.getTransactionType());
        dto.setAmount(transaction.getAmount());
        dto.setBalanceBefore(transaction.getBalanceBefore());
        dto.setBalanceAfter(transaction.getBalanceAfter());
        dto.setDescription(transaction.getDescription());
        dto.setCreateTime(transaction.getCreateTime());
        dto.setReferenceId(transaction.getReferenceId());
        return dto;
    }
}